import dash
from dash import dcc, html, Input, Output, State
import plotly.express as px
import pandas as pd

# 初始化 Dash 应用
app = dash.Dash(__name__)

# 创建一个空的 DataFrame 来存储点的数据
df = pd.DataFrame(columns=['x', 'y', 'z'])

# 定义应用的布局
app.layout = html.Div([
    html.H1("三维散点图绘制工具", style={'textAlign': 'center'}),
    dcc.Graph(id='3d-scatter-plot', style={'height': '600px'}),
    html.Div([
        html.Label("X 坐标:"),
        dcc.Input(id='x-input', type='number', placeholder='输入 X 坐标', style={'margin-right': '10px'}),
        html.Label("Y 坐标:"),
        dcc.Input(id='y-input', type='number', placeholder='输入 Y 坐标', style={'margin-right': '10px'}),
        html.Label("Z 坐标:"),
        dcc.Input(id='z-input', type='number', placeholder='输入 Z 坐标', style={'margin-right': '10px'}),
        html.Button('添加点', id='add-point-button', style={'margin-right': '10px'}),
        html.Button('清除所有点', id='clear-points-button')
    ], style={'margin-top': '20px', 'textAlign': 'center'}),
    html.Div(id='status-message', style={'margin-top': '10px', 'textAlign': 'center', 'color': 'red'})
])

# 定义回调函数，当点击按钮时添加点并更新图形
@app.callback(
    [Output('3d-scatter-plot', 'figure'),
     Output('status-message', 'children')],
    [Input('add-point-button', 'n_clicks'),
     Input('clear-points-button', 'n_clicks')],
    [State('x-input', 'value'),
     State('y-input', 'value'),
     State('z-input', 'value'),
     State('3d-scatter-plot', 'figure')]
)
def update_graph(add_clicks, clear_clicks, x, y, z, current_figure):
    global df
    ctx = dash.callback_context

    # 判断触发回调的按钮
    if not ctx.triggered:
        button_id = None
    else:
        button_id = ctx.triggered[0]['prop_id'].split('.')[0]

    # 清除所有点
    if button_id == 'clear-points-button':
        df = pd.DataFrame(columns=['x', 'y', 'z'])
        fig = px.scatter_3d(df, x='x', y='y', z='z')
        return fig, "所有点已清除。"

    # 添加点
    if button_id == 'add-point-button':
        if x is None or y is None or z is None:
            return current_figure, "请输入有效的 X、Y、Z 坐标！"

        # 添加新点到 DataFrame
        new_point = pd.DataFrame({'x': [x], 'y': [y], 'z': [z]})
        df = pd.concat([df, new_point], ignore_index=True)

        # 更新图形
        fig = px.scatter_3d(df, x='x', y='y', z='z')

        # 添加连线
        fig.update_traces(mode='lines+markers', line=dict(color='blue', width=2))

        return fig, f"点 ({x}, {y}, {z}) 已添加。"

    # 默认返回空图形
    return px.scatter_3d(df, x='x', y='y', z='z'), ""

# 运行应用
if __name__ == '__main__':
    app.run_server(debug=True)